package utn.frba.matematicasuperior.modelo;

import java.util.ArrayList;
import java.util.List;

import utn.frba.matematicasuperior.utiles.DiferenciaFinita;
import utn.frba.matematicasuperior.utiles.Orden;

public class Soporte {

	/************************************************************/
	/************************ ATRIBUTOS *************************/
	/************************************************************/

	private List<ParOrdenado> paresOrdenados;
	private DiferenciaFinita diferenciaFinita;

	/************************************************************/
	/*********************** PROPIEDADES ************************/
	/************************************************************/

	public DiferenciaFinita getDiferenciaFinita() {
		return diferenciaFinita;
	}

	public void setDiferenciaFinita(DiferenciaFinita diferenciaFinita) {
		this.diferenciaFinita = diferenciaFinita;
	}

	public List<ParOrdenado> getParesOrdenados() {
		return paresOrdenados;
	}

	public void setParesOrdenados(List<ParOrdenado> paresOrdenados) {
		this.paresOrdenados = paresOrdenados;
	}

	/************************************************************/
	/*********************** CONSTRUCTOR ************************/
	/************************************************************/

	public Soporte(List<ParOrdenado> listaSoporte) {
		this.paresOrdenados = listaSoporte;
		this.diferenciaFinita = this.calcularDiferenciaFinita(
				this.obtenerAbcisas(), this.obtenerOrdenadas(), 1);
	}

	/************************************************************/
	/******************** METODOS PUBLICOS **********************/
	/************************************************************/

	public List<Double> obtenerAbcisas() {

		List<Double> abcisas = new ArrayList<>();

		for (ParOrdenado par : this.paresOrdenados) {
			abcisas.add(par.getX());
		}

		return abcisas;
	}

	public List<Double> obtenerOrdenadas() {

		List<Double> ordenadas = new ArrayList<>();

		for (ParOrdenado par : this.paresOrdenados) {
			ordenadas.add(par.getY());
		}

		return ordenadas;

	}

	/************************************************************/
	/******************** METODOS PRIVADOS **********************/
	/************************************************************/

	private DiferenciaFinita calcularDiferenciaFinita(List<Double> abcisas,
			List<Double> ordenadas, int orden) {

		if (orden == Orden.PRIMER_ORDEN) {
			diferenciaFinita = new DiferenciaFinita();
			Orden primerOrden = new Orden(Orden.ZERO_ORDEN);
			primerOrden.setCoeficientes(ordenadas);
			diferenciaFinita.agregarNuevoOrden(primerOrden);
		}

		int j = 0;
		int salto = orden;

		Orden ordenK = new Orden(salto);

		while (diferenciaFinita.getOrdenes().size() < abcisas.size()) {

			while (j < abcisas.size() - salto) {
				Double diferencia = (ordenadas.get(j + 1) - ordenadas.get(j))
						/ (abcisas.get(j + salto) - abcisas.get(j));
				ordenK.agregarCoeficiente(diferencia);
				j++;
			}

			diferenciaFinita.agregarNuevoOrden(ordenK);

			calcularDiferenciaFinita(abcisas, ordenK.getCoeficientes(),
					orden + 1);
		}

		return diferenciaFinita;
	}

	public List<Double> obtenerDiferenciaFinitaRegresiva() {

		List<Double> coeficientes = new ArrayList<Double>();

		for (Orden orden : this.getDiferenciaFinita().getOrdenes()) {
			coeficientes.add(orden.getCoeficientes().get(
					orden.getCoeficientes().size() - 1));
		}

		return coeficientes;
	}

	public List<Double> obtenerDiferenciaFinitaProgresiva() {

		List<Double> coeficientes = new ArrayList<Double>();

		for (Orden orden : this.getDiferenciaFinita().getOrdenes()) {
			coeficientes.add(orden.getCoeficientes().get(0));
		}

		return coeficientes;
	}
}
